﻿using NetMicro.Trace.Extensions;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Diagnostics;

namespace NetMicro.Trace.Enricher
{
    /// <summary>
    /// 链路扩展
    /// </summary>
    public class ActivityEnricher : ILogEventEnricher
    {
        private const string SpanId = "SpanId";
        private const string TraceId = "TraceId";
        private const string ParentId = "ParentId";

        private const string SpanIdKey = "Serilog.SpanId";
        private const string TraceIdKey = "Serilog.TraceId";
        private const string ParentIdKey = "Serilog.ParentId";


        /// <summary>
        /// 日志事件
        /// </summary>
        /// <param name="logEvent"></param>
        /// <param name="propertyFactory"></param>
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            ArgumentNullException.ThrowIfNull(logEvent);
            var activity = Activity.Current;

            if (activity is not null)
            {

                AddSpanId(logEvent, activity);
                AddTraceId(logEvent, activity);
                AddParentId(logEvent, activity);

            }
        }


        private static void AddSpanId(LogEvent logEvent, Activity activity)
        {
            var property = activity.GetCustomProperty(SpanIdKey);
            if (property is null || property is not LogEventProperty logEventProperty)
            {
                logEventProperty = new LogEventProperty(SpanId, new ScalarValue(activity.GetSpanId()));
                activity.SetCustomProperty(SpanIdKey, logEventProperty);
            }

            logEvent.AddPropertyIfAbsent(logEventProperty);
        }

        private static void AddTraceId(LogEvent logEvent, Activity activity)
        {
            var property = activity.GetCustomProperty(TraceIdKey);
            if (property is null || property is not LogEventProperty logEventProperty)
            {
                logEventProperty = new LogEventProperty(TraceId, new ScalarValue(activity.GetTraceId()));
                activity.SetCustomProperty(TraceIdKey, logEventProperty);
            }

            logEvent.AddPropertyIfAbsent(logEventProperty);
        }

        private static void AddParentId(LogEvent logEvent, Activity activity)
        {
            var property = activity.GetCustomProperty(ParentIdKey);
            if (property is null || property is not LogEventProperty logEventProperty)
            {
                logEventProperty = new LogEventProperty(ParentId, new ScalarValue(activity.GetParentId()));
                activity.SetCustomProperty(ParentIdKey, logEventProperty);
            }

            logEvent.AddPropertyIfAbsent(logEventProperty);
        }

    }
}
